home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / nr3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  25.2 KB  |  1,032 lines

  1. /* net/rom level 3 low level processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "iface.h"
  11. #include "netuser.h"
  12. #include "arp.h"
  13. #include "slip.h"
  14. #include "ax25.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "lapb.h"
  18. #include "socket.h"
  19. #include "trace.h"
  20. #include "ip.h"
  21. #include "commands.h"
  22.  
  23. static int accept_bc __ARGS((char *addr,unsigned ifnum));
  24. static struct nr_bind *find_best __ARGS((struct nr_bind *list,unsigned obso));
  25. static struct nr_bind *find_binding __ARGS((struct nr_bind *list,struct nrnbr_tab *neighbor));
  26. static struct nrnbr_tab *find_nrnbr __ARGS((char *, unsigned));
  27. static struct nrnf_tab *find_nrnf __ARGS((char *, unsigned));
  28. static struct nr_bind *find_worst __ARGS((struct nr_bind *list));
  29. static int ismycall __ARGS((char *addr));
  30. #ifdef    notdef
  31. static char *nr_getroute __ARGS((char *));
  32. #endif
  33. static void nr3arp __ARGS((void));
  34. static struct raw_nr *Raw_nr;
  35. int nr_aliasck __ARGS((char *alias));
  36.  
  37. /* Nodes message broadcast address: "NODES" in shifted ASCII */
  38. char Nr_nodebc[AXALEN] = {
  39.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
  40.     ('0'<<1) | E
  41. };
  42.  
  43. struct nriface Nrifaces[NRNUMIFACE];
  44. unsigned Nr_numiface;
  45. struct nrnbr_tab *Nrnbr_tab[NRNUMCHAINS];
  46. struct nrroute_tab *Nrroute_tab[NRNUMCHAINS];
  47. struct nrnf_tab *Nrnf_tab[NRNUMCHAINS];
  48. unsigned Nr_nfmode = NRNF_NOFILTER;
  49. unsigned short Nr_ttl = 64;
  50. static unsigned Obso_init = 6;
  51. static unsigned Obso_minbc = 5;
  52. static unsigned Nr_maxroutes = 5;
  53. static unsigned Nr_autofloor = 1;
  54. int Nr_verbose = 0;
  55. struct iface *Nr_iface;
  56.  
  57. /* send a NET/ROM layer 3 datagram */
  58. void
  59. nr3output(dest, data)
  60. char *dest;
  61. struct mbuf *data;
  62. {
  63.     struct nr3hdr n3hdr;
  64.     struct mbuf *n3b;
  65.  
  66.     memcpy(n3hdr.dest,dest,AXALEN);    /* copy destination field */
  67.     n3hdr.ttl = Nr_ttl;    /* time to live from initializer parm */
  68.  
  69.     if((n3b = htonnr3(&n3hdr)) == NULLBUF){
  70.         free_p(data);
  71.         return;
  72.     }
  73.     append(&n3b, data);
  74.     /* The null interface indicates that the packet needs to have */
  75.     /* an appropriate source address inserted by nr_route */
  76.     nr_route(n3b,NULLAX25);
  77. }
  78.  
  79. /* send IP datagrams across a net/rom network connection */
  80. int
  81. nr_send(bp,iface,gateway,prec,del,tput,rel)
  82. struct mbuf *bp;
  83. struct iface *iface;
  84. int32 gateway;
  85. int prec;
  86. int del;
  87. int tput;
  88. int rel;
  89. {
  90.     struct arp_tab *arp;
  91.  
  92.     dump(iface,IF_TRACE_OUT,TYPE_NETROM,bp);
  93.     if((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP){
  94.         free_p(bp);    /* drop the packet if no route */
  95.         return -1;
  96.     }
  97.     nr_sendraw(arp->hw_addr, NRPROTO_IP, NRPROTO_IP, bp);
  98.     return 0;
  99. }
  100.  
  101. /* Send arbitrary protocol data on top of a NET/ROM connection */
  102. void
  103. nr_sendraw(dest,family,proto,data)
  104. char *dest;
  105. unsigned family;
  106. unsigned proto;
  107. struct mbuf *data;
  108. {
  109.     struct mbuf *pbp;
  110.     struct nr4hdr n4hdr;
  111.  
  112.     /* Create a "network extension" transport header */
  113.     n4hdr.opcode = NR4OPPID;
  114.     n4hdr.u.pid.family = family;
  115.     n4hdr.u.pid.proto = proto;
  116.  
  117.     if((pbp = htonnr4(&n4hdr)) == NULLBUF){
  118.         free_p(data);
  119.         return;
  120.     }
  121.     append(&pbp,data);        /* Append the data to that */
  122.     nr3output(dest, pbp); /* and pass off to level 3 code */
  123. }
  124.  
  125. /* Arrange for receipt of raw NET/ROM datagrams */
  126. struct raw_nr *
  127. raw_nr(protocol)
  128. char protocol;
  129. {
  130.     register struct raw_nr *rp;
  131.  
  132.     rp = (struct raw_nr *)callocw(1,sizeof(struct raw_nr));
  133.     rp->protocol = protocol;
  134.     rp->next = Raw_nr;
  135.     if(rp->next != NULLRNR)
  136.         rp->next->prev = rp;
  137.     Raw_nr = rp;
  138.     return rp;
  139. }
  140. /* Free a raw NET/ROM descriptor */
  141. void
  142. del_rnr(rpp)
  143. struct raw_nr *rpp;
  144. {
  145.     register struct raw_nr *rp;
  146.  
  147.     /* Do sanity check on arg */
  148.     for(rp = Raw_nr;rp != NULLRNR;rp = rp->next)
  149.         if(rp == rpp)
  150.             break;
  151.     if(rp == NULLRNR)
  152.         return;    /* Doesn't exist */
  153.  
  154.     /* Unlink */
  155.     if(rp->prev != NULLRNR)
  156.         rp->prev->next = rp->next;
  157.     else
  158.         Raw_nr = rp->next;
  159.     if(rp->next != NULLRNR)
  160.         rp->next->prev = rp->prev;
  161.     /* Free resources */
  162.     free_q(&rp->rcvq);
  163.     free((char *)rp);
  164. }
  165.  
  166. /* Figure out if a call is assigned to one of my net/rom
  167.  * interfaces.
  168.  */
  169. static int
  170. ismycall(addr)
  171. char *addr;
  172. {
  173.     register int i;
  174.     int found = 0;
  175.     
  176.     for(i = 0; i < Nr_numiface; i++)
  177.         if(addreq(Nrifaces[i].iface->hwaddr,addr)){
  178.             found = 1;
  179.             break;
  180.         }
  181.  
  182.     return found;
  183. }
  184.  
  185.  
  186. /* Route net/rom network layer packets.
  187.  */
  188. void
  189. nr_route(bp, iaxp)
  190. struct mbuf *bp;            /* network packet */
  191. struct ax25_cb *iaxp;            /* incoming ax25 control block */
  192. {
  193.     struct nr3hdr n3hdr;
  194.     struct nr4hdr n4hdr;
  195.     struct ax25_cb *axp;
  196.     struct mbuf *hbp, *pbp;
  197.     struct raw_nr *rnr;
  198.     register struct nrnbr_tab *np;
  199.     register struct nrroute_tab *rp;
  200.     register struct nr_bind *bindp;
  201.     struct iface *iface;
  202.     unsigned ifnum;
  203.     
  204.     if(ntohnr3(&n3hdr,&bp) == -1){
  205.         free_p(bp);
  206.         return;
  207.     }
  208.     /* If this isn't an internally generated network packet,
  209.      * give the router a chance to record a route back to the
  210.      * sender, in case they aren't in the local node's routing
  211.      * table yet.
  212.      */
  213.     if(iaxp != NULLAX25 && ax_lookup(iaxp->remote) != NULLAXR){
  214.             
  215.         /* find the interface number */
  216.         for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  217.             if(iaxp->iface == Nrifaces[ifnum].iface)
  218.                 break;
  219.  
  220.         if(ifnum == Nr_numiface){    /* Not a net/rom interface! */
  221.             free_p(bp);
  222.             return;
  223.         }
  224.         /* Add (possibly) a zero-quality recorded route via */
  225.         /* the neighbor from which this packet was received */
  226.         /* Note that this doesn't work with digipeated neighbors. */
  227.         
  228.         (void) nr_routeadd("      ",n3hdr.source,ifnum,0,iaxp->remote,0,1);
  229.     }
  230.  
  231.     /* A packet from me, to me, can only be one thing:
  232.      * a horrible routing loop.  This will probably result
  233.      * from a bad manual ARP entry, but we should fix these
  234.      * obscure errors as we find them.
  235.      */
  236.     if(ismycall(n3hdr.dest)){
  237.         /* Toss if from me, or if we can't read the header */
  238.         if(iaxp == NULLAX25 || ntohnr4(&n4hdr,&bp) == -1){
  239.             free_p(bp);
  240.         } else if((n4hdr.opcode & NR4OPCODE) == NR4OPPID){
  241.             for(rnr = Raw_nr;rnr!=NULLRNR;rnr = rnr->next){
  242.                 if(rnr->protocol!=n4hdr.u.pid.family ||
  243.                  rnr->protocol != n4hdr.u.pid.proto)
  244.                     continue;
  245.                 /* Duplicate the data portion, and put the
  246.                  * level 3 header back on
  247.                  */
  248.                 dup_p(&pbp,bp,0,len_p(bp));
  249.                 if(pbp != NULLBUF &&
  250.                  (hbp = htonnr3(&n3hdr)) != NULLBUF){
  251.                     append(&hbp,pbp);
  252.                     enqueue(&rnr->rcvq,hbp);
  253.                 } else {
  254.                     free_p(pbp);
  255.                     free_p(hbp);
  256.                 }
  257.             }
  258.             /* IP does not use a NET/ROM level 3 socket */
  259.             if(n4hdr.u.pid.family == NRPROTO_IP
  260.              && n4hdr.u.pid.proto == NRPROTO_IP)
  261.                 ip_route(iaxp->iface,bp,0);
  262.             else        /* we don't do this proto */
  263.                 free_p(bp);
  264.         } else {
  265.             /* Must be net/rom transport: */
  266.             nr4input(&n4hdr,bp);
  267.         }
  268.         return;
  269.     }
  270.     if((rp = find_nrroute(n3hdr.dest)) == NULLNRRTAB){
  271.         /* no route, drop the packet */
  272.         free_p(bp);
  273.         return;
  274.     }
  275.     if((bindp = find_best(rp->routes,1)) == NULLNRBIND){
  276.         /* This shouldn't happen yet, but might if we add */
  277.         /* dead route detection */
  278.         free_p(bp);
  279.         return;
  280.     }
  281.  
  282.     np = bindp->via;
  283.     iface = Nrifaces[np->iface].iface;
  284.  
  285.     /* Now check to see if iaxp is null.  That is */
  286.     /* a signal that the packet originates here, */
  287.     /* so we need to insert the callsign of the appropriate  */
  288.     /* interface */
  289.     if(iaxp == NULLAX25)
  290.         memcpy(n3hdr.source,iface->hwaddr,AXALEN);
  291.     
  292.     /* Make sure there is a connection to the neighbor */
  293.     if((axp = find_ax25(np->call)) == NULLAX25 ||
  294.         (axp->state != LAPB_CONNECTED && axp->state != LAPB_RECOVERY)){
  295.         /* Open a new connection or reinitialize old one */
  296.         /* hwaddr has been advanced to point to neighbor + digis */
  297.         axp = open_ax25(iface,iface->hwaddr,np->call, AX_ACTIVE, Axwindow, s_arcall, s_atcall, s_ascall,-1);
  298.         if(axp == NULLAX25){
  299.             free_p(bp);
  300.             return;
  301.         }
  302.     }
  303.         
  304.     if(--n3hdr.ttl == 0){    /* the packet's time to live is over! */
  305.         free_p(bp);
  306.         return;
  307.     }
  308.     /* now format network header */
  309.     if((pbp = htonnr3(&n3hdr)) == NULLBUF){
  310.         free_p(bp);
  311.         return;
  312.     }
  313.     append(&pbp,bp);        /* append data to header */
  314.  
  315.     /* put AX.25 PID on front */
  316.     if((bp = pushdown(pbp,1)) == NULLBUF){
  317.         free_p(pbp);
  318.         return;
  319.     }
  320.     bp->data[0] = PID_NETROM;
  321.  
  322.     if((pbp = segmenter(bp,axp->paclen)) == NULLBUF){
  323.         free_p(bp);
  324.         return;
  325.     }
  326.     send_ax25(axp,pbp,-1);    /* pass it off to ax25 code */
  327. }
  328.     
  329.  
  330. /* Perform a nodes broadcast on interface # ifno in the net/rom
  331.  * interface table.
  332.  */
  333. void
  334. nr_bcnodes(ifno)
  335. unsigned ifno;
  336. {
  337.     struct mbuf *hbp, *dbp, *savehdr;
  338.     struct nrroute_tab *rp;
  339.     struct nrnbr_tab *np;
  340.     struct nr_bind * bp;
  341.     struct nr3dest nrdest;
  342.     int i, didsend = 0, numdest = 0;
  343.     register char *cp;
  344.     struct iface *axif = Nrifaces[ifno].iface;
  345.     
  346.     /* prepare the header */
  347.     if((hbp = alloc_mbuf(NR3NODEHL)) == NULLBUF)
  348.         return;
  349.         
  350.     hbp->cnt = NR3NODEHL;    
  351.     
  352.     *hbp->data = NR3NODESIG;
  353.     memcpy(hbp->data+1,Nrifaces[ifno].alias,ALEN);
  354.  
  355.     /* Some people don't want to advertise any routes; they
  356.      * just want to be a terminal node.  In that case we just
  357.      * want to send our call and alias and be done with it.
  358.      */
  359.  
  360.     if(!Nr_verbose){
  361.         (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  362.                         PID_NETROM, hbp);    /* send it */
  363.         return;
  364.     }
  365.  
  366.     /* make a copy of the header in case we need to send more than */
  367.     /* one packet */
  368.     savehdr = copy_p(hbp,NR3NODEHL);
  369.  
  370.     /* now scan through the routing table, finding the best routes */
  371.     /* and their neighbors.  create destination subpackets and append */
  372.     /* them to the header */
  373.     for(i = 0; i < NRNUMCHAINS; i++){
  374.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next){
  375.             /* look for best, non-obsolescent route */
  376.             if((bp = find_best(rp->routes,0)) == NULLNRBIND)
  377.                 continue;    /* no non-obsolescent routes found */
  378.             if(bp->quality == 0)    /* this is a loopback route */
  379.                 continue;    /* we never broadcast these */
  380.             if (nr_aliasck(rp->alias))    /* corrupted alias entry? */
  381.                 continue ;        /* don't rebroadcast it */
  382.             np = bp->via;
  383.             /* insert best neighbor */
  384.             memcpy(nrdest.neighbor,np->call,AXALEN);
  385.             /* insert destination from route table */
  386.             memcpy(nrdest.dest,rp->call,AXALEN);
  387.             /* insert alias from route table */
  388.             strcpy(nrdest.alias,rp->alias);
  389.             /* insert quality from binding */
  390.             nrdest.quality = bp->quality;
  391.             /* create a network format destination subpacket */
  392.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  393.                 free_p(hbp);    /* drop the whole idea ... */
  394.                 free_p(savehdr);
  395.                 return;
  396.             }
  397.             /* we now have a partially filled packet */
  398.             didsend = 0;    
  399.             append(&hbp,dbp);/* append to header and others */
  400.             /* see if we have appended as many destinations
  401.              * as we can fit into a single broadcast.  If we
  402.              * have, go ahead and send them out.
  403.              */
  404.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  405.                 /* indicate that we did broadcast */
  406.                 didsend = 1;
  407.                 /* reset the destination counter */
  408.                 numdest = 0;
  409.                 (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  410.                  PID_NETROM,hbp);    /* send it */
  411.                 /* new header */
  412.                 hbp = copy_p(savehdr,NR3NODEHL);
  413.             }
  414.         }
  415.     }
  416.  
  417.     /* Now, here is something totally weird.  If our interfaces */
  418.     /* have different callsigns than this one, advertise a very */
  419.     /* high quality route to them.  Is this a good idea?  I don't */
  420.     /* know.  However, it allows us to simulate a bunch of net/roms */
  421.     /* hooked together with a diode matrix coupler. */
  422.     for(i = 0; i < Nr_numiface; i++){
  423.         if(i == ifno)
  424.             continue;        /* don't bother with ours */
  425.         cp = Nrifaces[i].iface->hwaddr;
  426.         if(!addreq((char *)axif->hwaddr,cp)){
  427.             /* both destination and neighbor address */
  428.             memcpy(nrdest.dest,cp,AXALEN);
  429.             memcpy(nrdest.neighbor,cp,AXALEN);
  430.             /* alias of the interface */
  431.             strcpy(nrdest.alias,Nrifaces[i].alias);
  432.             /* and the very highest quality */
  433.             nrdest.quality = 255;
  434.             /* create a network format destination subpacket */
  435.             if((dbp = htonnrdest(&nrdest)) == NULLBUF){
  436.                 free_p(hbp);    /* drop the whole idea ... */
  437.                 free_p(savehdr);
  438.                 return;
  439.             }
  440.             /* we now have a partially filled packet */
  441.             didsend = 0;    
  442.             /* append to header and others */
  443.             append(&hbp,dbp);
  444.             if(++numdest == NRDESTPERPACK){    /* filled it up */
  445.                 /* indicate that we did broadcast */
  446.                 didsend = 1;
  447.                 /* reset the destination counter */
  448.                 numdest = 0;
  449.                 (*axif->output)(axif, Nr_nodebc, axif->hwaddr,
  450.                  PID_NETROM,hbp);    /* send it */
  451.                 /* new header */
  452.                 hbp = copy_p(savehdr,NR3NODEHL);
  453.             }
  454.         }
  455.     }
  456.             
  457.     /* If we have a partly filled packet left over, or we never */
  458.     /* sent one at all, we broadcast: */
  459.     if(!didsend || numdest > 0)
  460.         (*axif->output)(axif, Nr_nodebc, axif->hwaddr,PID_NETROM, hbp);
  461.  
  462.     /* free the header copies */
  463.     if(numdest == 0)
  464.         free_p(hbp);
  465.     free_p(savehdr);
  466. }
  467.  
  468.  
  469. /* initialize fake arp entry for netrom */
  470. static void
  471. nr3arp()
  472. {
  473.  
  474.     arp_init(ARP_NETROM,AXALEN,0,0,0,NULLCHAR,pax25,setcall);
  475. }
  476.  
  477. /* attach the net/rom interface.  no parms for now. */
  478. int
  479. nr_attach(argc,argv,p)
  480. int argc;
  481. char *argv[];
  482. void *p;
  483. {
  484.     if(Nr_iface != (struct iface *)0){
  485.         tprintf("netrom interface already attached\n");
  486.         return -1;
  487.     }
  488.  
  489.     nr3arp();
  490.     
  491.     Nr_iface = (struct iface *)callocw(1,sizeof(struct iface));
  492.     Nr_iface->addr = Ip_addr;
  493.  
  494.     /* The strdup is needed to keep the detach routine happy (it'll
  495.      * free the allocated memory)
  496.      */
  497.     Nr_iface->name = strdup("netrom");
  498.     if(Nr_iface->hwaddr == NULLCHAR){
  499.         Nr_iface->hwaddr = mallocw(AXALEN);
  500.         memcpy(Nr_iface->hwaddr,Mycall,AXALEN);
  501.     }
  502.     Nr_iface->mtu = NR4MAXINFO;
  503.     setencap(Nr_iface,"NETROM");
  504.     Nr_iface->next = Ifaces;
  505.     Ifaces = Nr_iface;
  506.     memcpy(Nr4user,Mycall,AXALEN);
  507.     return 0;
  508. }
  509.  
  510. /* This function checks an ax.25 address and interface number against
  511.  * the filter table and mode, and returns 1 if the address is to be
  512.  * accepted, and 0 if it is to be filtered out.
  513.  */
  514. static int
  515. accept_bc(addr,ifnum)
  516. char *addr;
  517. unsigned ifnum;
  518. {
  519.     struct nrnf_tab *fp;
  520.  
  521.     if(Nr_nfmode == NRNF_NOFILTER)        /* no filtering in effect */
  522.         return 1;
  523.  
  524.     fp = find_nrnf(addr,ifnum);        /* look it up */
  525.     
  526.     if((fp != NULLNRNFTAB && Nr_nfmode == NRNF_ACCEPT)
  527.         || (fp == NULLNRNFTAB && Nr_nfmode == NRNF_REJECT))
  528.         return 1;
  529.     else
  530.         return 0;
  531. }
  532.  
  533.  
  534. /* receive and process node broadcasts. */
  535. void
  536. nr_nodercv(iface,source,bp)
  537. struct iface *iface;
  538. char *source;
  539. struct mbuf *bp;
  540. {
  541.     register int ifnum;
  542.     char bcalias[AXALEN];
  543.     struct nr3dest ds;
  544.     
  545.     /* First, see if this is even a net/rom interface: */
  546.     for(ifnum = 0; ifnum < Nr_numiface; ifnum++)
  547.         if(iface == Nrifaces[ifnum].iface)
  548.             break;
  549.             
  550.     if(ifnum == Nr_numiface){    /* not in the interface table */
  551.         free_p(bp);
  552.         return;
  553.     }
  554.  
  555.     if(!accept_bc(source,ifnum)){    /* check against filter */
  556.         free_p(bp);
  557.         return;
  558.     }
  559.     
  560.     /* See if it has a routing broadcast signature: */
  561.     if(uchar(pullchar(&bp)) != NR3NODESIG){
  562.         free_p(bp);
  563.         return;
  564.     }
  565.  
  566.     /* now try to get the alias */
  567.     if(pullup(&bp,bcalias,ALEN) < ALEN){
  568.         free_p(bp);
  569.         return;
  570.     }
  571.  
  572.     /* now check that the alias field is not corrupted - saftey measure! */
  573.     if (nr_aliasck(bcalias)) {
  574.         free_p(bp);
  575.         return;
  576.     }
  577.  
  578.     bcalias[ALEN] = '\0';        /* null terminate */
  579.  
  580.     /* enter the neighbor into our routing table */
  581.     if(nr_routeadd(bcalias,source,ifnum,Nrifaces[ifnum].quality,
  582.      source, 0, 0) == -1){
  583.         free_p(bp);
  584.         return;
  585.     }
  586.     
  587.     /* we've digested the header; now digest the actual */
  588.     /* routing information */
  589.     while(ntohnrdest(&ds,&bp) != -1){
  590.         /* ignore routes to me! */
  591.         if(ismycall(ds.dest))
  592.             continue;
  593.         /* ignore routes with corrupted aliases - safety measure */
  594.         if (nr_aliasck (ds.alias))
  595.             continue;
  596.         /* ignore routes below the minimum quality threshhold */
  597.         if(ds.quality < Nr_autofloor)
  598.             continue;
  599.         /* set loopback paths to 0 quality */
  600.         if(ismycall(ds.neighbor))
  601.             ds.quality = 0;
  602.         else
  603.             ds.quality = ((ds.quality * Nrifaces[ifnum].quality + 128)
  604.              / 256) & 0xff;
  605.         if(nr_routeadd(ds.alias,ds.dest,ifnum,ds.quality,source,0,0)
  606.             == -1)
  607.             break;
  608.     }
  609.             
  610.     free_p(bp);    /* This will free the mbuf if anything fails above */
  611. }
  612.  
  613.  
  614. /* The following are utilities for manipulating the routing table */
  615.  
  616. /* hash function for callsigns.  Look familiar? */
  617. int16
  618. nrhash(s)
  619. char *s;
  620. {
  621.     register char x;
  622.     register int i;
  623.  
  624.     x = 0;
  625.     for(i = ALEN; i !=0; i--)
  626.         x ^= *s++ & 0xfe;
  627.     x ^= *s & SSID;
  628.     return (int16)(uchar(x) % NRNUMCHAINS);
  629. }
  630.  
  631. /* Find a neighbor table entry.  Neighbors are determined by
  632.  * their callsign and the interface number.  This takes care
  633.  * of the case where the same switch or hosts uses the same
  634.  * callsign on two different channels.  This isn't done by
  635.  * net/rom, but it might be done by stations running *our*
  636.  * software.
  637.  */
  638. static struct nrnbr_tab *
  639. find_nrnbr(addr,ifnum)
  640. register char *addr;
  641. unsigned ifnum;
  642. {
  643.     int16 hashval;
  644.     register struct nrnbr_tab *np;
  645.  
  646.     /* Find appropriate hash chain */
  647.     hashval = nrhash(addr);
  648.  
  649.     /* search hash chain */
  650.     for(np = Nrnbr_tab[hashval]; np != NULLNTAB; np = np->next){
  651.         /* convert first in  list to ax25 address format */
  652.         if(addreq(np->call,addr) && np->iface == ifnum){
  653.             return np;
  654.         }
  655.     }
  656.     return NULLNTAB;
  657. }
  658.  
  659.  
  660. /* Find a route table entry */
  661. struct nrroute_tab *
  662. find_nrroute(addr)
  663. register char *addr;
  664. {
  665.     int16 hashval;
  666.     register struct nrroute_tab *rp;
  667.  
  668.     /* Find appropriate hash chain */
  669.     hashval = nrhash(addr);
  670.  
  671.     /* search hash chain */
  672.     for(rp = Nrroute_tab[hashval]; rp != NULLNRRTAB; rp = rp->next){
  673.         if(addreq(rp->call,addr)){
  674.             return rp;
  675.         }
  676.     }
  677.     return NULLNRRTAB;
  678. }
  679.  
  680. /* Try to find the AX.25 address of a node with the given alias.  Return */
  681. /* a pointer to the AX.25 address if found, otherwise NULLCHAR.  The alias */
  682. /* should be a six character, blank-padded, upper-case string. */
  683.  
  684. char *
  685. find_nralias(alias)
  686. char *alias;
  687. {
  688.     int i;
  689.     register struct nrroute_tab *rp;
  690.  
  691.     /* Since the route entries are hashed by ax.25 address, we'll */
  692.     /* have to search all the chains */
  693.     
  694.     for(i = 0; i < NRNUMCHAINS; i++)
  695.         for(rp = Nrroute_tab[i]; rp != NULLNRRTAB; rp = rp->next)
  696.             if(strncmp(alias, rp->alias, 6) == 0)
  697.                 return rp->call;
  698.  
  699.     /* If we get to here, we're out of luck */
  700.  
  701.     return NULLCHAR;
  702. }
  703.  
  704.  
  705. /* Find a binding in a list by its neighbor structure's address */
  706. static struct nr_bind *
  707. find_binding(list,neighbor)
  708. struct nr_bind *list;
  709. register struct nrnbr_tab *neighbor;
  710. {
  711.     register struct nr_bind *bp;
  712.  
  713.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  714.         if(bp->via == neighbor)
  715.             return bp;
  716.  
  717.     return NULLNRBIND;
  718. }
  719.  
  720. /* Find the worst quality non-permanent binding in a list */
  721. static
  722. struct nr_bind *
  723. find_worst(list)
  724. struct nr_bind *list;
  725. {
  726.     register struct nr_bind *bp;
  727.     struct nr_bind *worst = NULLNRBIND;
  728.     unsigned minqual = 1000;    /* infinity */
  729.  
  730.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  731.         if(!(bp->flags & NRB_PERMANENT) && bp->quality < minqual){
  732.             worst = bp;
  733.             minqual = bp->quality;
  734.         }
  735.  
  736.     return worst;
  737. }
  738.  
  739. /* Find the best binding of any sort in a list.  If obso is 1,
  740.  * include entries below the obsolescence threshhold in the
  741.  * search (used when this is called for routing broadcasts).
  742.  * If it is 0, routes below the threshhold are treated as
  743.  * though they don't exist.
  744.  */
  745. static
  746. struct nr_bind *
  747. find_best(list,obso)
  748. struct nr_bind *list;
  749. unsigned obso;
  750. {
  751.     register struct nr_bind *bp;
  752.     struct nr_bind *best = NULLNRBIND;
  753.     int maxqual = -1;    /* negative infinity */
  754.  
  755.     for(bp = list; bp != NULLNRBIND; bp = bp->next)
  756.         if((int)bp->quality > maxqual)
  757.             if(obso || bp->obsocnt >= Obso_minbc){
  758.                 best = bp;
  759.                 maxqual = bp->quality;
  760.             }
  761.  
  762.     return best;
  763. }
  764.  
  765. /* Add a route to the net/rom routing table */
  766. int
  767. nr_routeadd(alias,dest,ifnum,quality,neighbor,permanent,record)
  768. char *alias;        /* net/rom node alias, blank-padded and */
  769.             /* null-terminated */
  770. char *dest;        /* destination node callsign */
  771. unsigned ifnum;    /* net/rom interface number */
  772. unsigned quality;    /* route quality */
  773. char *neighbor;    /* neighbor node + 2 digis (max) in arp format */
  774. unsigned permanent;    /* 1 if route is permanent (hand-entered) */
  775. unsigned record;    /* 1 if route is a "record route" */
  776. {
  777.     struct nrroute_tab *rp;
  778.     struct nr_bind *bp;
  779.     struct nrnbr_tab *np;
  780.     int16 rhash, nhash;
  781.  
  782.     /* See if a routing table entry exists for this destination */
  783.     if((rp = find_nrroute(dest)) == NULLNRRTAB){
  784.         rp = (struct nrroute_tab *)callocw(1,sizeof(struct nrroute_tab));
  785.         /* create a new route table entry */
  786.         strncpy(rp->alias,alias,6);
  787.         memcpy(rp->call,dest,AXALEN);
  788.         rhash = nrhash(dest);
  789.         rp->next = Nrroute_tab[rhash];
  790.         if(rp->next != NULLNRRTAB)
  791.             rp->next->prev = rp;
  792.         Nrroute_tab[rhash] = rp;    /* link at head of hash chain */
  793.     } else if(!record){
  794.         strncpy(rp->alias,alias,6);    /* update the alias */
  795.     }
  796.  
  797.     /* See if an entry exists for this neighbor */
  798.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB){
  799.         np = (struct nrnbr_tab *)callocw(1,sizeof(struct nrnbr_tab));
  800.         /* create a new neighbor entry */
  801.         memcpy(np->call,neighbor,AXALEN);
  802.         np->iface = ifnum;
  803.         nhash = nrhash(neighbor);
  804.         np->next = Nrnbr_tab[nhash];
  805.         if(np->next != NULLNTAB)
  806.             np->next->prev = np;
  807.         Nrnbr_tab[nhash] = np;
  808.     } else if(permanent){        /* force this path to the neighbor */
  809.         memcpy(np->call,neighbor,AXALEN);
  810.     }
  811.         
  812.     /* See if there is a binding between the dest and neighbor */
  813.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND){
  814.         bp = (struct nr_bind *)callocw(1,sizeof(struct nr_bind));
  815.         /* create a new binding and link it in */
  816.         bp->via = np;    /* goes via this neighbor */
  817.         bp->next = rp->routes;    /* link into binding chain */
  818.         if(bp->next != NULLNRBIND)
  819.             bp->next->prev = bp;
  820.         rp->routes = bp;
  821.         rp->num_routes++;    /* bump route count */
  822.         np->refcnt++;        /* bump neighbor ref count */
  823.         bp->quality = quality;
  824.         bp->obsocnt = Obso_init;    /* use initial value */
  825.         if(permanent)
  826.             bp->flags |= NRB_PERMANENT;
  827.         else if(record)    /* notice permanent overrides record! */
  828.             bp->flags |= NRB_RECORDED;
  829.     } else {
  830.         if(permanent){    /* permanent request trumps all */
  831.             bp->quality = quality;
  832.             bp->obsocnt = Obso_init;
  833.             bp->flags |= NRB_PERMANENT;
  834.             bp->flags &= ~NRB_RECORDED;    /* perm is not recorded */
  835.         } else if(!(bp->flags & NRB_PERMANENT)){    /* not permanent */
  836.             if(record){    /* came from nr_route */
  837.                 if(bp->flags & NRB_RECORDED){ /* no mod non-rec bindings */
  838.                     bp->quality = quality;
  839.                     bp->obsocnt = Obso_init; /* freshen recorded routes */
  840.                 }
  841.             } else {        /* came from a routing broadcast */
  842.                 bp->quality = quality;
  843.                 bp->obsocnt = Obso_init;
  844.                 bp->flags &= ~NRB_RECORDED; /* no longer a recorded route */
  845.             }
  846.         }
  847.     }
  848.  
  849.     /* Now, check to see if we have too many bindings, and drop */
  850.     /* the worst if we do */
  851.     if(rp->num_routes > Nr_maxroutes){
  852.         /* since find_worst never returns permanent entries, the */
  853.         /* limitation on number of routes is circumvented for    */
  854.         /* permanent routes */
  855.         if((bp = find_worst(rp->routes)) != NULLNRBIND){
  856.             nr_routedrop(dest,bp->via->call,bp->via->iface);
  857.         }
  858.     }
  859.  
  860.     return 0;
  861. }
  862.  
  863.  
  864. /* Drop a route to dest via neighbor */
  865. int
  866. nr_routedrop(dest,neighbor,ifnum)
  867. char *dest, *neighbor;
  868. unsigned ifnum;
  869. {
  870.     register struct nrroute_tab *rp;
  871.     register struct nrnbr_tab *np;
  872.     register struct nr_bind *bp;
  873.  
  874.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  875.         return -1;
  876.  
  877.     if((np = find_nrnbr(neighbor,ifnum)) == NULLNTAB)
  878.         return -1;
  879.  
  880.     if((bp = find_binding(rp->routes,np)) == NULLNRBIND)
  881.         return -1;
  882.  
  883.     /* drop the binding first */
  884.     if(bp->next != NULLNRBIND)
  885.         bp->next->prev = bp->prev;
  886.     if(bp->prev != NULLNRBIND)
  887.         bp->prev->next = bp->next;
  888.     else
  889.         rp->routes = bp->next;
  890.  
  891.     free((char *)bp);
  892.     rp->num_routes--;        /* decrement the number of bindings */
  893.     np->refcnt--;            /* and the number of neighbor references */
  894.     
  895.     /* now see if we should drop the route table entry */
  896.     if(rp->num_routes == 0){
  897.         if(rp->next != NULLNRRTAB)
  898.             rp->next->prev = rp->prev;
  899.         if(rp->prev != NULLNRRTAB)
  900.             rp->prev->next = rp->next;
  901.         else
  902.             Nrroute_tab[nrhash(dest)] = rp->next;
  903.  
  904.         free((char *)rp);
  905.     }
  906.  
  907.     /* and check to see if this neighbor can be dropped */
  908.     if(np->refcnt == 0){
  909.         if(np->next != NULLNTAB)
  910.             np->next->prev = np->prev;
  911.         if(np->prev != NULLNTAB)
  912.             np->prev->next = np->next;
  913.         else
  914.             Nrnbr_tab[nrhash(neighbor)] = np->next;
  915.  
  916.         free((char *)np);
  917.     }
  918.     
  919.     return 0;
  920. }
  921.  
  922. #ifdef    notused
  923. /* Find the best neighbor for destination dest, in arp format */
  924. static char *
  925. nr_getroute(dest)
  926. char *dest;
  927. {
  928.     register struct nrroute_tab *rp;
  929.     register struct nr_bind *bp;
  930.  
  931.     if((rp = find_nrroute(dest)) == NULLNRRTAB)
  932.         return NULLCHAR;
  933.  
  934.     if((bp = find_best(rp->routes,1)) == NULLNRBIND)    /* shouldn't happen! */
  935.         return NULLCHAR;
  936.  
  937.     return bp->via->call;
  938. }
  939. #endif    /* notused */
  940.  
  941. /* Find an entry in the filter table */
  942. static struct nrnf_tab *
  943. find_nrnf(addr,ifnum)
  944. register char *addr;
  945. unsigned ifnum;
  946. {
  947.     int16 hashval;
  948.     register struct nrnf_tab *fp;
  949.  
  950.     /* Find appropriate hash chain */
  951.     hashval = nrhash(addr);
  952.  
  953.     /* search hash chain */
  954.     for(fp = Nrnf_tab[hashval]; fp != NULLNRNFTAB; fp = fp->next){
  955.         if(addreq(fp->neighbor,addr) && fp->iface == ifnum){
  956.             return fp;
  957.         }
  958.     }
  959.  
  960.     return NULLNRNFTAB;
  961. }
  962.  
  963. /* Add an entry to the filter table.  Return 0 on success,
  964.  * -1 on failure
  965.  */
  966. int
  967. nr_nfadd(addr,ifnum)
  968. char *addr;
  969. unsigned ifnum;
  970. {
  971.     struct nrnf_tab *fp;
  972.     int16 hashval;
  973.     
  974.     if(find_nrnf(addr,ifnum) != NULLNRNFTAB)
  975.         return 0;    /* already there; it's a no-op */
  976.  
  977.     fp = (struct nrnf_tab *)callocw(1,sizeof(struct nrnf_tab));
  978.  
  979.     hashval = nrhash(addr);
  980.     memcpy(fp->neighbor,addr,AXALEN);
  981.     fp->iface = ifnum;
  982.     fp->next = Nrnf_tab[hashval];
  983.     if(fp->next != NULLNRNFTAB)
  984.         fp->next->prev = fp;
  985.     Nrnf_tab[hashval] = fp;
  986.  
  987.     return 0;
  988. }
  989.  
  990. /* Drop a neighbor from the filter table.  Returns 0 on success, -1
  991.  * on failure.
  992.  */
  993. int
  994. nr_nfdrop(addr,ifnum)
  995. char *addr;
  996. unsigned ifnum;
  997. {
  998.     struct nrnf_tab *fp;
  999.  
  1000.     if((fp = find_nrnf(addr,ifnum)) == NULLNRNFTAB)
  1001.         return -1;    /* not in the table */
  1002.  
  1003.     if(fp->next != NULLNRNFTAB)
  1004.         fp->next->prev = fp->prev;
  1005.     if(fp->prev != NULLNRNFTAB)
  1006.         fp->prev->next = fp->next;
  1007.     else
  1008.         Nrnf_tab[nrhash(addr)] = fp->next;
  1009.  
  1010.     free((char *)fp);
  1011.  
  1012.     return 0;
  1013. }
  1014. /*
  1015.  * Validate the alias field is good quality ascii to prevent network corruption
  1016.  */
  1017.  
  1018. int nr_aliasck(alias)
  1019. char *alias;            
  1020.  
  1021. {
  1022.     int x = ALEN;
  1023.     int c;
  1024.     while (x--) {
  1025.         c = *alias++;
  1026.         if (!isprint( (int) c) )        
  1027.             return 1;
  1028.     }
  1029.     return 0;
  1030. }
  1031.  
  1032.